cas shiro 前后端分离 登录_apache shiro安全框架 登录,记住我,前后台分离

最近做的项目,由于客户需求,登录的用户信息必须经过身份验证,自己研究了一下,写个博客与大家分享一下我的心得。本次项目用到了shiro的登录,记住我,前后台分离功能。这里只做了登录认证,没有权限管理。

项目构建:

在pom.xml文件:

org.apache.shiro

shiro-spring

1.2.3

org.apache.shiro

shiro-web

1.2.3

org.apache.shiro

shiro-ehcache

1.2.3

org.apache.shiro

shiro-cas

1.2.3

在 web.xml文件里:

contextConfigLocation

classpath:applicationContext.xml,classpath:shiro/spring-context-shiro.xml

shiroFilter

org.springframework.web.filter.DelegatingFilterProxy

shiroFilter

/*

shrio配置文件  spring-context-shiro:<?xml version="1.0" encoding="UTF-8"?>

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">

Shiro Configuration

/userMember/login = authc

/logout = logout

/apply/** = user

/alter/** = user

class="包路径.FormAuthenticationFilter">

class="包路径.SystemAuthorizingRealm" />

class="包路径.UserAuthorizingRealm" />

class="包路径.SystemAuthorizingRealm">

class="包路径.UserAuthorizingRealm">

class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">

class="org.apache.shiro.web.mgt.CookieRememberMeManager">

value="#{T(org.apache.shiro.codec.Base64).decode('4AvVhmFLUs0KTA3Kprsdag==')}"/>

class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO">

在这里有一个 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 definedRealms;

/**

* 多个realm实现

*/

@Override

protected AuthenticationInfo doMultiRealmAuthentication(Collection 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 getDefinedRealms() {

return this.definedRealms;

}

public void setDefinedRealms(Map definedRealms) {

this.definedRealms = definedRealms;

}

}

SystemAuthorizingRealm  后台认证realmpackage 包路径;

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 前台用户认证realmpackage 包路径.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 {

/**

* 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页面:

pageEncoding="UTF-8"%>

登录

登录成功以后,如何显示的登录者的用户名。在这里shrio有自己的页面标签:

首先导入 标签:

登录|

注册

这里详细的就不贴出了,也就不详细说明了。只是告诉大家,有这样一个途径,就不用费尽心思的还要把信息封装到session 里面了。一开始,我不知道有这样的途径,所以,把信息封装到了session里面了,这真的是多此一举。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值