一、概念
Shiro是一个Java安全框架,可以帮助我们完成:认证、授权、加密、会话管理、与Web集成、缓存等。

Subject:即当前用户,在权限管理的应用程序里往往需要知道谁能够操作什么,谁拥有操作该程序的权利,shiro中则需要通过Subject来提供基础的当前用户信息,Subject 不仅仅代表某个用户,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物。
SecurityManager:管理所有Subject,这是Shiro框架的核心组件,可以把他看做是一个Shiro框架的全局管理组件,用于调度各种Shiro框架的服务。
Realm:域,Shiro从从Realm获取安全数据(如用户、角色、权限),可以看成数据库。
认证流程:

使用流程:
1. 自定义realm
3.提交认证,将携带的信息储存在 UsernamePasswordToken中
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username,password);
4.获取subject
Subject subject = SecurityUtils.getSubject();
5.登录
subject.login(usernamePasswordToken);
二、代码
代码层级

1.pom文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>springboot-shiro-10095</artifactId>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.2.RELEASE</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.44</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.4</version>
</dependency>
<!-- shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
2.application.yml
server:
port: 10095
spring:
application:
name: shiro
# zipkin:
# base-url: http://127.0.0.1:10092
#eureka
#eureka:
# client:
# service-url:
# defaultZone: http://localhost:10090/eureka/
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/shiro?useUnicode=true&characterEncoding=UTF-8
username: root
password: root
type: com.alibaba.druid.pool.DruidDataSource
jpa:
show-sql: true
hibernate:
ddl-auto: update
http:
encoding:
charset: utf-8
enabled: true
3.关于shiro的表5张,利用JPA自动生成
(1)User 用户表
/**
* All rights Reserved
* @Title: User.java
* @Package com.yanwu.www.entity
* @Description: TODO(用一句话描述该文件做什么)
* @author: harvey
* @date: 2018年8月30日 下午2:05:58
* @version V1.0
* @Copyright: 2018
*/
package com.yanwu.www.entity;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
/**
* @ClassName: User
* @Description:TODO(这里用一句话描述这个类的作用)
* @author: harvey
* @date: 2018年8月30日 下午2:05:58
*
* @Copyright: 2018
*/
@Entity(name="user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private String password;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
(2)Role 角色表
/**
* All rights Reserved
* @Title: Role.java
* @Package com.yanwu.www.entity
* @Description: TODO(用一句话描述该文件做什么)
* @author: harvey
* @date: 2018年8月30日 下午2:07:43
* @version V1.0
* @Copyright: 2018
*/
package com.yanwu.www.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
/**
* @ClassName: Role
* @Description:TODO(这里用一句话描述这个类的作用)
* @author: harvey
* @date: 2018年8月30日 下午2:07:43
*
* @Copyright: 2018
*/
@Entity
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String roleName;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
}
(3)Permission 权限表
/**
* All rights Reserved
* @Title: Permission.java
* @Package com.yanwu.www.entity
* @Description: TODO(用一句话描述该文件做什么)
* @author: harvey
* @date: 2018年8月30日 下午2:12:42
* @version V1.0
* @Copyright: 2018
*/
package com.yanwu.www.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
/**
* @ClassName: Permission
* @Description:TODO(这里用一句话描述这个类的作用)
* @author: harvey
* @date: 2018年8月30日 下午2:12:42
*
* @Copyright: 2018
*/
@Entity
public class Permission {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String permission;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getPermission() {
return permission;
}
public void setPermission(String permission) {
this.permission = permission;
}
}
(4)UserRole 用户和角色关联
/**
* All rights Reserved
* @Title: UserRole.java
* @Package com.yanwu.www.entity
* @Description: TODO(用一句话描述该文件做什么)
* @author: harvey
* @date: 2018年8月30日 下午2:15:24
* @version V1.0
* @Copyright: 2018
*/
package com.yanwu.www.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
/**
* @ClassName: UserRole
* @Description:TODO(这里用一句话描述这个类的作用)
* @author: harvey
* @date: 2018年8月30日 下午2:15:24
*
* @Copyright: 2018
*/
@Entity
public class UserRole {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String userId;
private String roleId;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getRoleId() {
return roleId;
}
public void setRoleId(String roleId) {
this.roleId = roleId;
}
}
(5)RolePermission 角色和权限关联
/**
* All rights Reserved
* @Title: RolePermission.java
* @Package com.yanwu.www.entity
* @Description: TODO(用一句话描述该文件做什么)
* @author: harvey
* @date: 2018年8月30日 下午2:17:02
* @version V1.0
* @Copyright: 2018
*/
package com.yanwu.www.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
/**
* @ClassName: RolePermission
* @Description:TODO(这里用一句话描述这个类的作用)
* @author: harvey
* @date: 2018年8月30日 下午2:17:02
*
* @Copyright: 2018
*/
@Entity
public class RolePermission {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String roleId;
private String permissionId;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getRoleId() {
return roleId;
}
public void setRoleId(String roleId) {
this.roleId = roleId;
}
public String getPermissionId() {
return permissionId;
}
public void setPermissionId(String permissionId) {
this.permissionId = permissionId;
}
}
4.自定义realm(需要继承AuthorizingRealm)
/**
* All rights Reserved
* @Title: UserRealm.java
* @Package com.yanwu.www.config
* @Description: TODO(用一句话描述该文件做什么)
* @author: harvey
* @date: 2018年8月30日 下午2:48:54
* @version V1.0
* @Copyright: 2018
*/
package com.yanwu.www.config;
import java.util.List;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.yanwu.www.entity.Permission;
import com.yanwu.www.entity.Role;
import com.yanwu.www.entity.User;
import com.yanwu.www.repository.PermissionRipository;
import com.yanwu.www.repository.RoleRipository;
import com.yanwu.www.repository.UserRipository;
/**
* @ClassName: UserRealm
* @Description: 自定义realm
* @author: harvey
* @date: 2018年8月30日 下午2:48:54
*
* @Copyright: 2018
*/
@Component
public class MyShiroRealm extends AuthorizingRealm{
@Autowired
private UserRipository userRipository;
@Autowired
private RoleRipository roleRipository;
@Autowired
private PermissionRipository permissionRipository;
/**
* <p>Title: doGetAuthorizationInfo</p>
* <p>Description: </p>
* @param arg0
* @return
* @see org.apache.shiro.realm.AuthorizingRealm#doGetAuthorizationInfo(org.apache.shiro.subject.PrincipalCollection)
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//获取登录用户名
String username= (String) principalCollection.getPrimaryPrincipal();
//查询用户名称
User user = userRipository.findByName(username);
//添加角色和权限
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
List<Role> roles = roleRipository.findRolesByUserId(user.getId().toString());
for(Role role : roles){
// 添加角色
simpleAuthorizationInfo.addRole(role.getRoleName());
for(Permission permission : permissionRipository.findPermissionsByRoleId(role.getId().toString())){
// 添加权限
simpleAuthorizationInfo.addStringPermission(permission.getPermission());
}
}
return simpleAuthorizationInfo;
}
/**
* <p>Title: doGetAuthenticationInfo</p>
* <p>Description: </p>
* @param arg0
* @return
* @throws AuthenticationException
* @see org.apache.shiro.realm.AuthenticatingRealm#doGetAuthenticationInfo(org.apache.shiro.authc.AuthenticationToken)
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// 1.把AuthenticationToken转为UsernamePasswordToken对象
UsernamePasswordToken upToken = (UsernamePasswordToken) token;
// 2.从UsernamePasswordToken获取username
String userName = upToken.getUsername();
// 3.调用数据库方法,从数据库中查询username对应的用户记录
System.out.println("从数据库中获取信息userName:" + userName + "所对应信息");
User user = userRipository.findByName(userName);
// 4.若用户不存在,则可以抛出异常
if (null == user) {
throw new UnknownAccountException("用户不存在");
}
// 5.根据用户情况,来构建AuthenticationInfo对象并返回,通常使用的实现类是SimpleAuthenticationInfo
// 1)principal,用户名,认证实体,可以是实体,也可以是数据表对应的实体类对象
Object principal = userName;
// 2)credential,密码,明文密码,即构建UsernamePasswordToken对象时的密码
Object credentials = user.getPassword().toString();
// 3)realmName:当前realm对象的name,调用父类的getName即可
String realmName = getName();
// 4.盐值(避免同一密码加密时产生相同的字符串,一般是用用户名做盐值)
ByteSource credentialsSalt = ByteSource.Util.bytes(userName);
// 不加密
//SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal, credentials, realmName);
// 加密
SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(principal,credentials, credentialsSalt, realmName);
return info;
}
// 增加用户时可以使用SimpleHash产生加密后的密码字符串存入数据库,避免数据库的用户密码明文显示
public static void main(String[] args) {
String algorithmName="MD5";
Object source="1234";
Object salt=ByteSource.Util.bytes("user2");
int hashIterations=1024;
Object result=new SimpleHash(algorithmName, source, salt, hashIterations);
System.out.println(result);
}
}
5.shiro配置类
/**
* All rights Reserved
* @Title: ShiroConfig.java
* @Package com.yanwu.www.config
* @Description: TODO(用一句话描述该文件做什么)
* @author: harvey
* @date: 2018年8月30日 下午2:47:16
* @version V1.0
* @Copyright: 2018
*/
package com.yanwu.www.config;
import java.util.HashMap;
import java.util.Map;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @ClassName: ShiroConfig
* @Description:shiro配置类
* @author: harvey
* @date: 2018年8月30日 下午2:47:16
*
* @Copyright: 2018
*/
@Configuration
public class ShiroConfig {
/**
* 密码校验规则HashedCredentialsMatcher
* 这个类是为了对密码进行编码的 ,
* 防止密码在数据库里明码保存 , 当然在登陆认证的时候 ,
* 这个类也负责对form里输入的密码进行编码
* 处理认证匹配处理器:如果自定义需要实现继承HashedCredentialsMatcher
*/
@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher() {
HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
//指定加密方式为MD5
credentialsMatcher.setHashAlgorithmName("MD5");
//加密次数
credentialsMatcher.setHashIterations(1024);
credentialsMatcher.setStoredCredentialsHexEncoded(true);
return credentialsMatcher;
}
//将自己的验证方式加入容器
@Bean
public MyShiroRealm myShiroRealm() {
MyShiroRealm myShiroRealm = new MyShiroRealm();
// 设置加密方式
myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
return myShiroRealm;
}
//权限管理,配置主要是Realm的管理认证
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myShiroRealm());
return securityManager;
}
//Filter工厂,设置对应的过滤条件和跳转条件
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
Map<String,String> map = new HashMap<String, String>();
//anon表示可以匿名访问,authc表示需要认证
//登出
map.put("/logout","anon");
//对所有用户认证
map.put("/**","authc");
//登录
shiroFilterFactoryBean.setLoginUrl("/login");
//首页
shiroFilterFactoryBean.setSuccessUrl("/index");
//错误页面,认证不通过跳转
shiroFilterFactoryBean.setUnauthorizedUrl("/error");
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
return shiroFilterFactoryBean;
}
//加入注解的使用,不加入这个注解不生效
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
}
6.Repositoty
(1)BaseRepository
package com.yanwu.www.repository;
import java.io.Serializable;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.PagingAndSortingRepository;
/**
*
* @ClassName: BaseRepository
* @Description:TODO(这里用一句话描述这个类的作用)
* @author: harvey
* @date: 2018年8月30日 下午2:21:18
*
* @param <T>
* @param <I>
* @Copyright: 2018
*/
@NoRepositoryBean
public interface BaseRepository<T,I extends Serializable> extends PagingAndSortingRepository<T,I>,JpaSpecificationExecutor<T>{
}
(2)UserRipository
/**
* All rights Reserved
* @Title: UserRipository.java
* @Package com.yanwu.www.repository
* @Description: TODO(用一句话描述该文件做什么)
* @author: harvey
* @date: 2018年8月30日 下午2:20:19
* @version V1.0
* @Copyright: 2018
*/
package com.yanwu.www.repository;
import org.springframework.stereotype.Repository;
import com.yanwu.www.entity.User;
/**
* @ClassName: UserRipository
* @Description:TODO(这里用一句话描述这个类的作用)
* @author: harvey
* @date: 2018年8月30日 下午2:20:19
*
* @Copyright: 2018
*/
@Repository
public interface UserRipository extends BaseRepository<User, Long>{
User findByName(String username);
}
(3)RoleRipository
/**
* All rights Reserved
* @Title: UserRipository.java
* @Package com.yanwu.www.repository
* @Description: TODO(用一句话描述该文件做什么)
* @author: harvey
* @date: 2018年8月30日 下午2:20:19
* @version V1.0
* @Copyright: 2018
*/
package com.yanwu.www.repository;
import java.util.List;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import com.yanwu.www.entity.Role;
/**
* @ClassName: UserRipository
* @Description:TODO(这里用一句话描述这个类的作用)
* @author: harvey
* @date: 2018年8月30日 下午2:20:19
*
* @Copyright: 2018
*/
@Repository
public interface RoleRipository extends BaseRepository<Role, Long>{
@Query(value = "select distinct r.* from role r inner join role_permission rp on rp.role_id = r.id inner join user_role ur on ur.role_id = r.id where ur.user_id =?1" ,nativeQuery=true)
List<Role> findRolesByUserId(String userId);
}
(4)PermissionRipository
/**
* All rights Reserved
* @Title: UserRipository.java
* @Package com.yanwu.www.repository
* @Description: TODO(用一句话描述该文件做什么)
* @author: harvey
* @date: 2018年8月30日 下午2:20:19
* @version V1.0
* @Copyright: 2018
*/
package com.yanwu.www.repository;
import java.util.List;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import com.yanwu.www.entity.Permission;
/**
* @ClassName: UserRipository
* @Description:TODO(这里用一句话描述这个类的作用)
* @author: harvey
* @date: 2018年8月30日 下午2:20:19
*
* @Copyright: 2018
*/
@Repository
public interface PermissionRipository extends BaseRepository<Permission, Long>{
@Query(value = "select distinct p.* from permission p inner join role_permission rp on rp.permission_id = p.id inner join role r on r.id = rp.role_id where r.id =?1" ,nativeQuery=true)
List<Permission> findPermissionsByRoleId(String roleId);
}
7.service
(1)UserService
/**
* All rights Reserved
* @Title: UserService.java
* @Package com.yanwu.www.service
* @Description: TODO(用一句话描述该文件做什么)
* @author: harvey
* @date: 2018年8月30日 下午2:25:11
* @version V1.0
* @Copyright: 2018
*/
package com.yanwu.www.service;
/**
* @ClassName: UserService
* @Description:TODO(这里用一句话描述这个类的作用)
* @author: harvey
* @date: 2018年8月30日 下午2:25:11
*
* @Copyright: 2018
*/
public interface UserService {
/**
*
* @Title: login
* @Description: 用户登录
* @param username
* @param password
* @return
* @return: String
*/
String login(String username,String password);
/**
*
* @Title: logout
* @Description: 用户登出
* @return
* @return: String
*/
String logout();
}
(2)UserServiceImpl
/**
* All rights Reserved
* @Title: UserServiceImpl.java
* @Package com.yanwu.www.service
* @Description: TODO(用一句话描述该文件做什么)
* @author: harvey
* @date: 2018年8月30日 下午2:27:15
* @version V1.0
* @Copyright: 2018
*/
package com.yanwu.www.service;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
/**
* @ClassName: UserServiceImpl
* @Description:TODO(这里用一句话描述这个类的作用)
* @author: harvey
* @date: 2018年8月30日 下午2:27:15
*
* @Copyright: 2018
*/
@Component
public class UserServiceImpl implements UserService {
/**
* <p>Title: login</p>
* <p>Description: </p>
* @param username
* @param password
* @see com.yanwu.www.service.UserService#login(java.lang.String, java.lang.String)
*/
@Override
public String login(String username, String password) {
if(StringUtils.isEmpty(username) || StringUtils.isEmpty(password)){
throw new UnknownAccountException("账号或者密码为空");
}
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username,password);
Subject subject = SecurityUtils.getSubject();
try{
subject.login(usernamePasswordToken);
// 设置闲置session时间
subject.getSession().setTimeout(5*1000);
return "login ok";
}catch( AuthenticationException e){
System.out.println("==========");
System.out.println(e.getMessage());
}
return "login failure";
}
/**
* <p>Title: logout</p>
* <p>Description: </p>
* @return
* @see com.yanwu.www.service.UserService#logout()
*/
@Override
public String logout() {
Subject subject = SecurityUtils.getSubject();
subject.logout();
return "logout ok";
}
}
8.controller
/**
* All rights Reserved
* @Title: UserController.java
* @Package com.yanwu.www.controller
* @Description: TODO(用一句话描述该文件做什么)
* @author: harvey
* @date: 2018年8月30日 下午3:31:43
* @version V1.0
* @Copyright: 2018
*/
package com.yanwu.www.controller;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.yanwu.www.service.UserService;
/**
* @ClassName: UserController
* @Description:TODO(这里用一句话描述这个类的作用)
* @author: harvey
* @date: 2018年8月30日 下午3:31:43
*
* @Copyright: 2018
*/
@RestController
public class UserController {
@Autowired
private UserService userService;
//登录
@RequestMapping(value = "/login")
public String login(String username,String password){
String status = userService.login(username, password);
return status;
}
//首页
@RequestMapping(value = "/index")
public String index(){
return "index";
}
//登出
@RequestMapping(value = "/logout")
public String logout(){
userService.logout();
return "logout";
}
//错误页面展示
@RequestMapping(value = "/error",method = RequestMethod.POST)
public String error(){
return "error ok!";
}
// 测试shiro注解
@RequestMapping(value = "/test",method = RequestMethod.GET)
@RequiresRoles(value={"admin"})
public String test(){
return "test ok!";
}
}
三、注意点
加密
本博客已经配置,需要在自定义realm,securityManager进行修改,如下配置如何获得加密后的字符串
// 增加用户时可以使用SimpleHash产生加密后的密码字符串存入数据库,避免数据库的用户密码明文显示
public static void main(String[] args) {
String algorithmName="MD5";
Object source="1234";
// 加盐
Object salt=ByteSource.Util.bytes("user2");
int hashIterations=1024;
Object result=new SimpleHash(algorithmName, source, salt, hashIterations);
System.out.println(result);
}