耀眼的橘子
2017-04-18 14:20:45
apache shiro安全框架 登录,记住我,前后台分离
最近做的项目,由于客户需求,登录的用户信息必须经过身份验证,自己研究了一下,写个博客与大家分享一下我的心得。本次项目用到了shiro的登录,记住我,前后台分离功能。这里只做了登录认证,没有权限管理。
项目构建:
在pom.xml文件:
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.2.3 </version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.2.3 </version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.2.3 </version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-cas</artifactId>
<version>1.2.3 </version>
</dependency>
在 web.xml文件里:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml,classpath:shiro/spring-context-shiro.xml</param-value>
</context-param>
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
shrio配置文件 spring-context-shiro:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"
default-lazy-init="true">
<description>Shiro Configuration</description>
<!--多个realm 的集中管理 -->
<bean id="defineModularRealmAuthenticator" class="包路径.DefautModularRealm">
<property name="definedRealms">
<map>
<entry key="systemAuthorizingRealm" value-ref="systemAuthorizingRealm" />
<entry key="userAuthorizingRealm" value-ref="userAuthorizingRealm" />
</map>
</property>
<!-- <property name="authenticationStrategy">
<bean class="org.apache.shiro.authc.pam.FirstSuccessfulStrategy" />
</property> -->
</bean>
<!-- Shiro权限过滤过滤器定义 -->
<bean name="shiroFilterChainDefinitions" class="java.lang.String">
<constructor-arg>
<value>
/userMember/login = authc
/logout = logout
/apply/** = user
/alter/** = user
</value>
</constructor-arg>
</bean>
<!-- 安全认证过滤器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="/userMember/login" />
<property name="successUrl" value="/home/forward" />
<property name="filters">
<map>
<entry key="cas" value-ref="casFilter" />
<entry key="authc" value-ref="formAuthenticationFilter" />
<entry key="logout" value-ref="logoutFilter" />
</map>
</property>
<property name="filterChainDefinitions">
<ref bean="shiroFilterChainDefinitions" />
</property>
</bean>
<bean id="logoutFilter" class="org.apache.shiro.web.filter.authc.LogoutFilter">
<property name="redirectUrl" value="/home/forward" />
</bean>
<bean id="casFilter" class="org.apache.shiro.cas.CasFilter">
<!--配置验证错误时的失败页面 /main 为系统登录页面 -->
<property name="failureUrl" value="/message.jsp" />
</bean>
<!-- 基于Form表单的身份验证过滤器 -->
<bean id="formAuthenticationFilter"
class="包路径.FormAuthenticationFilter">
<property name="usernameParam" value="name" />
<property name="passwordParam" value="password" />
<property name="logintypeParam" value="logintype" />
<property name="loginUrl" value="/login.jsp" />
<property name="rememberMeParam" value="rememberMe"/>
</bean>
<!-- 定义Shiro安全管理配置 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="authenticator" ref="defineModularRealmAuthenticator" />
<!-- 这里主要是设置自定义的单Realm应用,若有多个Realm,可使用'realms'属性代替 -->
<!-- <property name="realm" ref="loginRealm"/> -->
<property name="realms" >
<list>
<bean id="systemAuthorizingRealm"
class="包路径.SystemAuthorizingRealm" />
<bean id="userAuthorizingRealm"
class="包路径.UserAuthorizingRealm" />
</list>
</property>
<!-- <property name="sessionManager" ref="sessionManager" /> -->
<property name="cacheManager" ref="memoryConstrainedCacheManager" />
<property name="rememberMeManager" ref="rememberMeManager"/>
</bean>
<bean id="systemAuthorizingRealm"
class="包路径.SystemAuthorizingRealm">
</bean>
<bean id="userAuthorizingRealm"
class="包路径.UserAuthorizingRealm">
</bean>
<!-- 定义授权缓存管理器 -->
<bean id="shiroCacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<property name="cacheManager" ref="cacheManager" />
</bean>
<bean id="memoryConstrainedCacheManager" class="org.apache.shiro.cache.MemoryConstrainedCacheManager" />
<!-- 自定义会话管理配置 -->
<!-- 指定本系统SESSIONID, 默认为: JSESSIONID 问题: 与SERVLET容器名冲突, 如JETTY, TOMCAT 等默认JSESSIONID,
当跳出SHIRO SERVLET时如ERROR-PAGE容器会为JSESSIONID重新分配值导致登录会话丢失! -->
<bean id="sessionManager"
class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
<property name="sessionDAO" ref="sessionDAO" />
<!-- 会话超时时间,单位:毫秒 -->
<property name="globalSessionTimeout" value="${session.sessionTimeout}" />
<!-- 定时清理失效会话, 清理用户直接关闭浏览器造成的孤立会话 -->
<property name="sessionValidationInterval" value="${session.sessionTimeoutClean}" />
<!-- <property name="sessionValidationSchedulerEnabled" value="false"/> -->
<property name="sessionValidationSchedulerEnabled" value="true" />
<property name="sessionIdCookie" ref="sessionIdCookie" />
<property name="sessionIdCookieEnabled" value="true" />
</bean>
<!-- 会话Cookie模板 -->
<bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
<constructor-arg name="name" value="applyid" />
<property name="httpOnly" value="true"/>
<property name="maxAge" value="-1"/>
</bean>
<bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
<constructor-arg value="rememberMe"/>
<property name="httpOnly" value="true"/>
<property name="maxAge" value="604800"/><!-- 7天 -->
</bean>
<!-- rememberMe管理器 -->
<bean id="rememberMeManager"
class="org.apache.shiro.web.mgt.CookieRememberMeManager">
<property name="cipherKey"
value="#{T(org.apache.shiro.codec.Base64).decode('4AvVhmFLUs0KTA3Kprsdag==')}"/>
<property name="cookie" ref="rememberMeCookie"/>
</bean>
<bean id="sessionDAO"
class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO">
<!-- <property name="activeSessionsCacheName" value="shiro-activeSessionCache"/> -->
<property name="cacheManager" ref="shiroCacheManager" />
</bean>
<!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
</beans>
在这里有一个 logintype,这个变量是我,是我自定义的,本身的shrio是没有,是做前后台登录的标志位。
FormAuthenticationFilter 类:
package 包路径;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.FormAuthenticationFilter {
/**
* logger日志
*/
protected Logger logger = LoggerFactory.getLogger(getClass());
/**
* 序列化id
*/
private static final long serialVersionUID = -2271706136984114038L;
/**
* 登录类型
*/
public static final String DEFAULT_LOGINTYPE_PARAM = "logintype";
private String logintypeParam = DEFAULT_LOGINTYPE_PARAM;
protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {
String username = getUsername(request);
String password = getPassword(request);
String logintype = getLogintype(request);
logger.debug("createToken username:{},password:{},loginType:{"+logintype+"} ...",username,password);
if (password==null){
password = "";
}
String host = getRemoteAddr((HttpServletRequest)request);
boolean rememberMe = isRememberMe(request);
return new UsernamePasswordToken(username, password.toCharArray(), rememberMe, host, logintype);
}
public void setLogintypeParam(String logintypeParam) {
this.logintypeParam = logintypeParam;
}
public String getLogintypeParam() {
return logintypeParam;
}
protected String getLogintype(ServletRequest request) {
return WebUtils.getCleanParam(request, getLogintypeParam());
}
/**
* 获得用户远程地址
*/
public static String getRemoteAddr(HttpServletRequest request){
String remoteAddr = request.getHeader("X-Real-IP");
if (StringUtils.isNotBlank(remoteAddr)) {
remoteAddr = request.getHeader("X-Forwarded-For");
}else if (StringUtils.isNotBlank(remoteAddr)) {
remoteAddr = request.getHeader("Proxy-Client-IP");
}else if (StringUtils.isNotBlank(remoteAddr)) {
remoteAddr = request.getHeader("WL-Proxy-Client-IP");
}
return remoteAddr != null ? remoteAddr : request.getRemoteAddr();
}
}
UsernamePasswordToken 类:
package 包路径;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class UsernamePasswordToken extends org.apache.shiro.authc.UsernamePasswordToken {
/**
* logger日志
*/
protected Logger logger = LoggerFactory.getLogger(getClass());
/**
* 序列化id
*/
private static final long serialVersionUID = -2271706136984114038L;
/**
* 登录类型
*/
private String logintype ;
public String getLogintype() {
return logintype;
}
public void setLogintype(String logintype) {
this.logintype = logintype;
}
public UsernamePasswordToken (String username, char[] password,
boolean rememberMe, String host, String logintype) {
super(username, password, rememberMe, host);
this.logintype = logintype;
}
}
DefautModularRealm 类,多个realm集中管理:
package 包路径;
import java.util.Collection;
import java.util.Map;
import org.apache.shiro.ShiroException;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.util.CollectionUtils;
import 系统文件路径.SysConstant;
public class DefautModularRealm extends org.apache.shiro.authc.pam.ModularRealmAuthenticator{
private Map<String, Object> definedRealms;
/**
* 多个realm实现
*/
@Override
protected AuthenticationInfo doMultiRealmAuthentication(Collection<Realm> realms, AuthenticationToken token) {
return super.doMultiRealmAuthentication(realms, token);
}
/**
* 调用单个realm执行操作
*/
@Override
protected AuthenticationInfo doSingleRealmAuthentication(Realm realm,AuthenticationToken token) {
// 如果该realms不支持(不能验证)当前token
if (!realm.supports(token)) {
throw new ShiroException("token错误!");
}
AuthenticationInfo info = null;
try {
info = realm.getAuthenticationInfo(token);
if (info == null) {
throw new ShiroException("token不存在!");
}
} catch (Exception e) {
throw new ShiroException("用户名或者密码错误!");
}
return info;
}
/**
* 判断登录类型执行操作
*/
@Override
protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken)throws AuthenticationException {
this.assertRealmsConfigured();
Realm realm = null;
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
//判断是否是后台用户
if (token.getLogintype().equals(SysConstant.FRONT_LOGIN)) {
realm = (Realm) this.definedRealms.get("systemAuthorizingRealm");
}
else if (token.getLogintype().equals(SysConstant.ADMIN_LOGIN)){
realm = (Realm) this.definedRealms.get("userAuthorizingRealm");
}
return this.doSingleRealmAuthentication(realm, authenticationToken);
}
/**
* 判断realm是否为空
*/
@Override
protected void assertRealmsConfigured() throws IllegalStateException {
this.definedRealms = this.getDefinedRealms();
if (CollectionUtils.isEmpty(this.definedRealms)) {
throw new ShiroException("值传递错误!");
}
}
public Map<String, Object> getDefinedRealms() {
return this.definedRealms;
}
public void setDefinedRealms(Map<String, Object> definedRealms) {
this.definedRealms = definedRealms;
}
}
SystemAuthorizingRealm 后台认证realm
package 包路径;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import 系统文件路径.ENUM_SYSTEM;
import 系统文件路径.重写后台用户实体类.Principal;
import 系统文件路径.后台用户实体类.UserMemberDO;
import 系统文件路径.后台用户服务.UserMemberService;
@Service
public class SystemAuthorizingRealm extends AuthorizingRealm {
/**
* logger日志
*/
protected Logger logger = LoggerFactory.getLogger(getClass());
/**
* 序列化id
*/
private static final long serialVersionUID = -2271706136984114038L;
/**
* userMemberServicef服务
*/
@Resource
private UserMemberService userMemberService;
/**
* 授权
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addStringPermission("sys:manager");
info.addStringPermission("user");
System.out.println("开始授权");
return info;
}
/**
* 认证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
UserMemberDO user = userMemberService.getByName(token.getUsername());
if (user == null ) {
throw new UnknownAccountException("用户名不存在");
} else if (ENUM_SYSTEM.ACCOUNT_VERIFICATION_NO.getKey().equals(user.getStatus())) {
throw new DisabledAccountException("账户未审核通过!");
}
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(new Principal(user), user.getPassword(), null,
getName());
return authenticationInfo;
}
/**
* 设定密码校验的MD5算法与迭代次数
*/
@PostConstruct
public void initCredentialsMatcher() {
HashedCredentialsMatcher matcher = new HashedCredentialsMatcher("MD5");
setCredentialsMatcher(matcher);
}
@Override
protected void clearCachedAuthorizationInfo(PrincipalCollection principals) {
super.clearCachedAuthorizationInfo(principals);
}
@Override
protected void clearCachedAuthenticationInfo(PrincipalCollection principals) {
super.clearCachedAuthenticationInfo(principals);
}
@Override
protected void clearCache(PrincipalCollection principals) {
super.clearCache(principals);
}
public void clearAllCachedAuthorizationInfo() {
getAuthorizationCache().clear();
}
public void clearAllCachedAuthenticationInfo() {
getAuthenticationCache().clear();
}
public void clearAllCache() {
clearAllCachedAuthorizationInfo();
clearAllCachedAuthenticationInfo();
}
}
UserAuthorizingRealm 前台用户认证realm
package 包路径.shiro;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import 系统路径.ENUM_SYSTEM;
import 系统路径.重写前台用户实体类.user.Principal;
import 系统路径.前台用户实体类.user.UserDO;
import 系统路径.前台用户服务.user.UserService;
@Service
public class UserAuthorizingRealm extends AuthorizingRealm {
/**
* logger日志
*/
protected Logger logger = LoggerFactory.getLogger(getClass());
/**
* 序列化id
*/
private static final long serialVersionUID = -2271706136984114038L;
/**
* userMemberServicef服务
*/
@Resource
private UserService userService;
/**
* 授权
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addStringPermission("sys:manager");
info.addStringPermission("user");
System.out.println("开始授权");
return info;
}
/**
* 认证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
System.out.println(token.getUsername());
UserDO user = userService.getByName(token.getUsername());
if (user == null ) {
throw new UnknownAccountException("用户名不存在");
}
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(new Principal(user), user.getPassword(), null,
getName());
return authenticationInfo;
}
/**
* 设定密码校验的MD5算法与迭代次数
*/
@PostConstruct
public void initCredentialsMatcher() {
HashedCredentialsMatcher matcher = new HashedCredentialsMatcher("MD5");
setCredentialsMatcher(matcher);
}
@Override
protected void clearCachedAuthorizationInfo(PrincipalCollection principals) {
super.clearCachedAuthorizationInfo(principals);
}
@Override
protected void clearCachedAuthenticationInfo(PrincipalCollection principals) {
super.clearCachedAuthenticationInfo(principals);
}
@Override
protected void clearCache(PrincipalCollection principals) {
super.clearCache(principals);
}
public void clearAllCachedAuthorizationInfo() {
getAuthorizationCache().clear();
}
public void clearAllCachedAuthenticationInfo() {
getAuthenticationCache().clear();
}
public void clearAllCache() {
clearAllCachedAuthorizationInfo();
clearAllCachedAuthenticationInfo();
}
}
在这里有一个这样的一个类Principal这个类的作用主要是在用户登录的时候shiro保存登录信息,包括id ,姓名,密码,状态。等等。可以自定义。在JSP标签里的输出对象,在下面有讲。
前台登录controller:
package 系统路径.controller.usermember;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.alibaba.fastjson.JSON;
import 系统路径.前台用户实体类.Principal;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@Controller
@RequestMapping("userMember")
public class UserMemberController extends BaseController<UserMemberDO> {
/**
* logger日志
*/
protected Logger logger = LoggerFactory.getLogger(getClass());
/**
* 序列化id
*/
private static final long serialVersionUID = -2271706136984114038L;
/**
* 登录
* @param request 请求
* @param response 响应
* @param member 前台用户对象
* @param model 模板
* @return String 页面
*/
@RequestMapping(value = "/login")
public String login(HttpServletRequest request, HttpServletResponse response,
@ModelAttribute("member") UserMemberDO member, ModelMap model) {
logger.info("login...");
Subject subject = SecurityUtils.getSubject();
Principal principal = (Principal) subject.getPrincipal();
// 如果已经登录,则跳转到管理首页
if (principal != null) {
return "redirect:/home/forward"; // 首页
}
String exceptionClassName = (String) request.getAttribute("shiroLoginFailure");
String errorMsg = null;
if (UnknownAccountException.class.getName().equals(exceptionClassName)) {
logger.info("该用户名不存在");
errorMsg = "该用户名不存在";
} else if (IncorrectCredentialsException.class.getName().equals(exceptionClassName)) {
logger.info("密码错误");
errorMsg = "密码错误";
} else if (DisabledAccountException.class.getName().equals(exceptionClassName)) {
logger.info("该账号审核未通过");
errorMsg = "该账号审核未通过";
} else if (exceptionClassName != null) {
logger.info("登录错误" + exceptionClassName);
errorMsg = "登录错误";
}
model.addAttribute("errorMsg", errorMsg);
return PAGE_LOGIN;
}
}
这里我只写出前台登录的controller,后台的登录controller一样就不贴出了。
在JSP页面:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ include file="/view/common/include.jsp"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登录</title>
<script type="text/javascript" src="${ctxStatic }/js/login/login.js"></script>
<script>
</script>
</head>
<body>
<div class="container-login" id="div1">
<img src="${ctxStatic }/img/bj.png" />
</div>
<div class="container-login" id="div1">
<img src="${ctxStatic }/img/bj.png" />
</div>
<div class="content-all-login">
<div class="content-login">
<form action="${ctx}/userMember/login" method="post" id="loginform" >
<div class="content-title">
<h3>登录</h3>
</div>
<div class="form-group">
<input type="text" id="name" name="name" class="form-control text1" value="tom123" placeholder="输入用户名"/>
</div>
<div class="form-group">
<input type="password" id="password" name="password" value="000000"class="form-control text2" placeholder="密码"/>
<input type="text" id="logintype" name="logintype" value="0" style="display:none"/>
</div>
<div class="wrong"><label id="errorMsg">${errorMsg}</label></div>
<div class="row row-mian">
<div class="col-sm-6" style="padding-left: 0px;text-align: left;">
<input type="checkbox" value="true" id="rememberMe" name="rememberMe"/>
<span class="login-seven">七天免登陆<span>
</div>
<div class="col-sm-6" style="padding-right: 0px;text-align: right;">
<a href="" class="forgetPassword">忘记密码</a>
</div>
<div>
<button type="submit"class="btn btn-primary" style="margin-top: 25px;width: 232px;background: #0094fd;height: 40px;">登录</button>
</div>
</div>
</form>
</div>
</div>
</body>
</html>
登录成功以后,如何显示的登录者的用户名。在这里shrio有自己的页面标签:
首先导入 标签:
<%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<shiro:guest> <a href=""">登录</a>| <a href="" class="registered">注册</a> </shiro:guest>
<shiro:user>
<a class="login">你好:[<shiro:principal property="name"/>]</a>
<span id="center-info">
<ul>
<li class="dropdown" id="accountmenu" style="margin-right: 0px;">
<a class="center-in" style="width: 130px;display: inline-block;font-weight: 400;">
个人中心<b class="caret"></b></a>
<ul class="dropdown-menu" style="display: none;" id="center">
<li><a href="${ctx}/userMember/center" style="font-weight: 400;">基本信息</a></li>
<li><a href="${ctx}/userMember/history" style="font-weight: 400;">历史申请记录</a></li>
</ul>
</li>
</ul>
</span>
<a href="${ctx }/alter/message" class="login">消息</a>
<a href="${ctx }/logout" class="login">退出</a>
</shiro:user>
这里详细的就不贴出了,也就不详细说明了。只是告诉大家,有这样一个途径,就不用费尽心思的还要把信息封装到session 里面了。一开始,我不知道有这样的途径,所以,把信息封装到了session里面了,这真的是多此一举。
评论



最近浏览
