springboot+mybatis+shiro对url动态授权,同一账号登录,踢出最早登录(一)

编程

老规矩开始之前的两问:干什么,为什么这么干

场景:

根本问题:任何多用户的系统都存在身份鉴权。简单来说,不同用户在同一个系统有不同的操作,那么系统必然要识别用户。

产生问题:身份识别之后,对于一个系统来说,就可以进行正常使用,但是这个时候任何人都可以获得系统的信息,这就产生了授权。

为什么使用shiro?

shiro是一款专门用来身份识别与授权的框架

shiro能干什么?

进行身份识别和授权

开始:

1:pom.xml 引入相关包

<dependency>

<groupId>org.apache.shiro</groupId>

<artifactId>shiro-core</artifactId>

<version>1.2.2</version>

</dependency>

<dependency>

<groupId>org.apache.shiro</groupId>

<artifactId>shiro-web</artifactId>

<version>1.2.2</version>

</dependency>

<dependency>

<groupId>org.apache.shiro</groupId>

<artifactId>shiro-ehcache</artifactId>

<version>1.2.2</version>

</dependency>

<dependency>

<groupId>org.apache.shiro</groupId>

<artifactId>shiro-spring</artifactId>

<version>1.2.2</version>

</dependency>

2:首先是身份识别的问题,一般的我们都是通过输入的用户名和密码去数据库进行比对

那么对于shiro来说,我们只需要准备前端传的参数和数据库的参数,shiro就会为我们自动比对

(1)前端数据:

<from>

   <input name="username"/>

<input name="password">

<input type="submit">

</from>

  (2) 数据库

CREATE TABLE `fsp_user` (

`UUID` varchar(50) NOT NULL,

`F_NICKNAME` varchar(100) DEFAULT NULL,

`F_PASSWORD` varchar(100) DEFAULT NULL,

PRIMARY KEY (`UUID`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO

`fsp_user`

VALUES

("90feec5c-67bd-4fb2-b360-8b0387c4c009",

"admin",

"87632a5ef1d47286da9c1361717a1312");

  (3)登录比对 

  这一步是由shiro来完成,shiro需要知道我们的 输入参数和数据库的数据

  在此之前shiro需要初始化

 shiro的中心管理器是SecurityManager,那么第一步就是要配置SecurityManager

@Bean

public SecurityManager securityManager() {

//new 一个DefaultWebSecurityManager

DefaultSecurityManager defaultSecurityManager = new DefaultWebSecurityManager();

  //realm 就是从数据库取出数据比对登录

defaultSecurityManager.setRealm(myShiroRealm());

  //session管理器

defaultSecurityManager.setSessionManager(sessionManager());

  //cache管理器

defaultSecurityManager.setCacheManager(cacheManager());

  //我们需要对密码进行加密 使用md5,加密10次

HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher("md5");

hashedCredentialsMatcher.setHashIterations(10);

myShiroRealm().setCredentialsMatcher(hashedCredentialsMatcher);

SecurityUtils.setSecurityManager(defaultSecurityManager);

return defaultSecurityManager;

}

@Bean

//session 管理器

public DefaultWebSessionManager sessionManager(){

DefaultWebSessionManager defaultWebSessionManager = new DefaultWebSessionManager();

SimpleCookie simpleCookie= new SimpleCookie();

simpleCookie.setName("jeesite.session.id");

defaultWebSessionManager.setSessionIdCookie(simpleCookie);

defaultWebSessionManager.setSessionDAO(sessionDAO());

return defaultWebSessionManager;

}

//session的增删改查操作

@Bean

public MemorySessionDAO sessionDAO(){

return new MemorySessionDAO();

}

//cache管理器

@Bean

public CacheManager cacheManager(){

return new EhCacheManager();

}

@Bean

//取出数据库的数据 这个是我们自定义的

public UserRealm myShiroRealm(){

return new UserRealm();

}

//我们定义的数据源集成自AuthorizingRealm 

public class UserRealm extends AuthorizingRealm {

private Logger logger = LoggerFactory.getLogger(AuthorizingRealm.class);

  //数据库fsp_user 表对应的mybatis mapper接口

@Autowired

private FspUserDao fspUserDao;

 

//授权

@Override

protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();

return authorizationInfo;

}

//登录

@Override

protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

//1,获得前端传值

String username = (String) authenticationToken.getPrincipal();

  //去数据库查询

FspUser user = fspUserDao.isSelect("F_IPONE",username);

if (user == null) {

//没找到帐号

throw new UnknownAccountException();

}

SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user, user.getF_PASSWORD(), "");

//盐

authenticationInfo.setCredentialsSalt(ByteSource.Util.bytes("GGZEServer"));

user.setF_PASSWORD("");

//将用户信息放入session中

SecurityUtils.getSubject().getSession().setTimeout(-5000);

SecurityUtils.getSubject().getSession().setAttribute("FSPUSER", user);

return authenticationInfo;

}

/*//加密

public static void main(String[] args){

Md5Hash md5Hash = new Md5Hash("123456","GGZEServer",10);

System.out.println(md5Hash.toString());

}*/

}

(4)配置完成后,我们需要让所有的请求都是合法的,就必须进行登录,记住登录信息,每次的请求验证其合法性

我们使用过滤器来过滤所有请求,

首先要使shiro认识我们自定义的过滤器

@Bean

public AutoShiro shirFilter(SecurityManager securityManager, FspDataRecordDao fspDataRecordDao) {

System.out.println("ShiroConfiguration.shirFilter()");

ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

  // 过滤器链11

  Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();

 

  //key 为访问地址,value为权限。anao全部不过滤 authc为需要登录 loingout为登出

filterChainDefinitionMap.put("/css/**", "anon");

  filterChainDefinitionMap.put("/login", "authc");

  filterChainDefinitionMap.put("/img/**", "anon");

  filterChainDefinitionMap.put("/js/**", "anon");

  filterChainDefinitionMap.put("/loginout", "loginout");

shiroFilterFactoryBean.setSecurityManager(securityManager);

  //登录地址设置

shiroFilterFactoryBean.setLoginUrl("/vsp_8201574998956");

  //成功地址设置

shiroFilterFactoryBean.setSuccessUrl("/vsp_8201574998957");

Map<String, Filter> filters = new LinkedHashMap<String, Filter>();

AuthFilter authFilter=new AuthFilter();

authFilter.setLoginUrl("/login");

authFilter.setUsernameParam("F_IPONE");

authFilter.setPasswordParam("F_PASSWORD");

authFilter.setUserClass(FspUser.class);

  //设置过滤器名

filters.put("authc", authFilter);

  //这里可以设置自定义的过滤器

  //设置登出

LogoutFilter logoutFilter=new LogoutFilter();

filters.put("loginout",logoutFilter);

shiroFilterFactoryBean.setFilters(filters);

return shiroFilterFactoryBean;

}

按以上配置,shiro会认知shiro的过滤器,我们来实现它的过滤器

public class AuthFilter extends FormAuthenticationFilter {

private Class<? extends FspUser> userClass;

private static final String REDIRECT_URL_PARAMETER_NAME = "redirectUrl";

//创建身份认证

@Override

protected org.apache.shiro.authc.AuthenticationToken createToken(ServletRequest servletRequest, ServletResponse servletResponse) {

String username = getUsername(servletRequest);

String password = getPassword(servletRequest);

boolean rememberMe = isRememberMe(servletRequest);

String host = getHost(servletRequest);

return new UsernamePasswordToken(username, password, rememberMe, host);

}

/**

* 是否允许访问

*

* @param servletRequest ServletRequest

* @param servletResponse ServletResponse

* @param mappedValue 映射值

* @return 是否允许访问

*/

@Override

protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object mappedValue) {

Subject subject = getSubject(servletRequest, servletResponse);

Object principal = subject != null ? subject.getPrincipal() : null;

if (principal == null || !FspUser.class.isAssignableFrom(principal.getClass())) {

return false;

}

HttpServletRequest request=(HttpServletRequest) servletRequest;

if(request.getServletPath().indexOf("login")>=0&&request.getSession().getAttribute("FSPUSER")!=null){

HttpServletResponse response = (HttpServletResponse)servletResponse;

try {

response.sendRedirect("/shopc/vsp_8201574998957");

} catch (IOException e) {

e.printStackTrace();

}

}

return super.isAccessAllowed(servletRequest, servletResponse, mappedValue);

}

/**

* 拒绝访问处理

*

* @param servletRequest ServletRequest

* @param servletResponse ServletResponse

* @return 是否继续处理

*/

@Override

protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {

HttpServletRequest request = (HttpServletRequest) servletRequest;

HttpServletResponse response = (HttpServletResponse) servletResponse;

if (isLoginRequest(request, response)) {

if (isLoginSubmission(request, response)) {

return executeLogin(request, response);

} else {

return true;

}

}

response.sendRedirect("/shopc/vsp_8201574998956");

return false;

}

/**

* 登录成功处理

*

* @param authenticationToken 令牌

* @param subject Subject

* @param servletRequest ServletRequest

* @param servletResponse ServletResponse

* @return 是否继续处理

*/

@Override

protected boolean onLoginSuccess(org.apache.shiro.authc.AuthenticationToken authenticationToken, Subject subject, ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {

HttpServletRequest request = (HttpServletRequest) servletRequest;

HttpServletResponse response = (HttpServletResponse) servletResponse;

return super.onLoginSuccess(authenticationToken, subject, servletRequest, servletResponse);

}

/**

* 登录失败处理

*

* @param authenticationToken 令牌

* @param authenticationException 认证异常

* @param servletRequest ServletRequest

* @param servletResponse ServletResponse

* @return 是否继续处理

*/

@Override

protected boolean onLoginFailure(org.apache.shiro.authc.AuthenticationToken authenticationToken, AuthenticationException authenticationException, ServletRequest servletRequest, ServletResponse servletResponse) {

HttpServletRequest request = (HttpServletRequest) servletRequest;

HttpServletResponse response = (HttpServletResponse) servletResponse;

return super.onLoginFailure(authenticationToken, authenticationException, servletRequest, servletResponse);

}

public Class<? extends FspUser> getUserClass() {

return userClass;

}

public void setUserClass(Class<? extends FspUser> userClass) {

this.userClass = userClass;

}

public static String getRedirectUrlParameterName() {

return REDIRECT_URL_PARAMETER_NAME;

}

当执行创建身份认证的时候return new UsernamePasswordToken(username, password, rememberMe, host);

会进去我们自定义的Realm 登录成功。

已上传码云:https://gitee.com/wervernice/shirotest

未完待续

以上是 springboot+mybatis+shiro对url动态授权,同一账号登录,踢出最早登录(一) 的全部内容, 来源链接: utcz.com/z/512629.html

回到顶部